package edu.fau.scanny.r.stromal.servlet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;

import edu.fau.scanny.r.RUtils;
import edu.fau.scanny.r.stromal.RStromalFactory;
import edu.fau.scanny.r.stromal.RStromalFactory.Normalize;
import edu.fau.scanny.r.stromal.model.CelFile;
import edu.fau.scanny.r.stromal.model.IdTable;
import edu.fau.scanny.r.stromal.model.StromalCalculatorModel;
import edu.fau.scanny.r.stromal.model.StromalOutput;
import edu.fau.scanny.stromal.MetaFileUtils;


public class StromalCalculatorUtils {
	
	public static StromalCalculatorModel setUpStromalCalculatorModel(List<String> chips, Map<String, CelFile> chipCelFileMap, String normalization, boolean log2){
		Map<String,Map<String,List<CelFile>>> groupFilesMap = new LinkedHashMap<String,Map<String,List<CelFile>>>();
		List<CelFile> celFiles = new ArrayList<CelFile>();
		for (String chip : chips) {
			CelFile celFile = chipCelFileMap.get(chip);
			MetaFileUtils.updateMap(groupFilesMap, celFile.getTime()+ " "+celFile.getGroup(), celFile.getType(), celFile);
			celFiles.add(celFile);
		}
		StromalCalculatorModel model = new StromalCalculatorModel();
		model.setCelFiles(celFiles);
		model.setGroupFilesMap(groupFilesMap);
		model.setNormalizationMethod(getNormalizeOption(normalization));
		model.setLog2(log2);
		return model;
	}
	
	private static Normalize getNormalizeOption(String radio){
		if (radio.equalsIgnoreCase("rma"))
			return Normalize.RMA;
		else if (radio.equalsIgnoreCase("mas5"))
			return Normalize.MAS5;
		else if (radio.equalsIgnoreCase("plier"))
			return Normalize.PLIER;
		else if (radio.equalsIgnoreCase("plier16"))
			return Normalize.PLIER16;
		else 
			return Normalize.PLIER;
	}
	
	public static IdTable setUpIdTable(ServletConfig config){
		
		String mouseTable = config.getServletContext().getInitParameter("mouse4302");
		mouseTable = StringUtils.replace(config.getServletContext().getRealPath(mouseTable),"\\","/");
		IdTable idTable = new IdTable();
		idTable.setTableFile(mouseTable);
		idTable.setGeneCol(Integer.parseInt(config.getServletContext().getInitParameter("mouse4302_genes")));
		idTable.setEntrezCol(Integer.parseInt(config.getServletContext().getInitParameter("mouse4302_entrez")));
		idTable.setrTableVar("mouseTable");
		return idTable;
	}
	
	public static String readInFile(HttpServlet servlet, RConnection rc, String table, String param, Boolean headers, String rowNames, Boolean asIs) throws REngineException, REXPMismatchException{
		String file = servlet.getServletContext().getInitParameter(param);
		file = StringUtils.replace(servlet.getServletContext().getRealPath(file),"\\","/");
		RUtils.assign(rc, RUtils.readTable(file, headers, rowNames, "\\t", asIs), table);
		return file;
	}
	
	public static void asCharacterReadInFile(HttpServlet servlet, RConnection rc, String table, String param, Boolean headers, String rowNames, Boolean asIs) throws REngineException, REXPMismatchException{
		readInFile(servlet, rc, table, param, headers, rowNames, asIs);
		RUtils.assign(rc, RUtils.asCharacter(RUtils.unlist(table)), table);
	}
	
	
	public static boolean getBoolParam(HttpServletRequest req, String param, String trueParam) {
		String radio = req.getParameter(param);
		if (radio.equalsIgnoreCase(trueParam))
			return true;
		return false;
	}
	
	public static void errorHandling(Exception ex, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		req.setAttribute("error", ex.getMessage());
		req.getRequestDispatcher("error.jsp").forward(req, resp);
		ex.printStackTrace();
	}
	
	public static void setFileAttribute(HttpServletRequest req, RConnection rc, List<String> cols, String attribute, String fileDescription, IdTable idTable, File path, Map<String,StromalOutput> stromalOutputs, String normMethod, String scale)
			throws REngineException, REXPMismatchException, IOException {
		RUtils.cbind(rc, cols, attribute);
		File wtFile = RStromalFactory.signalFile(rc, attribute, fileDescription, idTable, path);
		
		List<String> plymphoids = new ArrayList<String>();
		for(Map.Entry<String, StromalOutput> entry: stromalOutputs.entrySet()){
			plymphoids.add(entry.getKey() + " P-lymphoid: " + entry.getValue().getPercentLymphoid());
		}
		
		String fileString = FileUtils.readFileToString(wtFile);
		fileString = String.format("%s\nNormalization method: %s\nScale: %s\n%s", StringUtils.join(plymphoids, "\n"), normMethod,scale, fileString);
		FileUtils.writeStringToFile(wtFile, fileString);
		req.setAttribute(attribute, wtFile);
	}


}
